package com.car.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.apache.log4j.Logger;
import org.springframework.ui.ModelMap;

import com.car.util.StringUtil;



public class ServiceExecutor {

	private void ServiceExecutor() {

	}

	public static ModelMap execute(Logger logger,
			AbstractValidator validator, Biz biz) {
		
		ModelMap modelMap = new ModelMap();
		ResultCode resultCode = new ResultCode();
		resultCode.init();
		logParams(logger, validator);

		if ( validator.validate()) {
			try {
				Result result = biz.process();
				logResult(logger, result);
				processResult(modelMap, result,resultCode);
			} catch (Exception e) {
				logger.error("unknow exception",e);
				resultCode.setParams((Integer)ResultCode.UNKNOW_ERROR_CODE[0], (String)ResultCode.UNKNOW_ERROR_CODE[1], ValidatorUtil.ERROR_SYSTEM);
			}

		} else {
			logger.error(ValidatorUtil.KEY_STATUS + " "
					+ ValidatorUtil.STATUS_FAIL + " "
					+ ValidatorUtil.KEY_ERROR_MSG + " " + validator.getErrMsg());
			resultCode.setParams((Integer)ResultCode.UNKNOW_ERROR_CODE[0], (String)ResultCode.UNKNOW_ERROR_CODE[1], validator.getErrMsg());
		}
		transfer(resultCode,modelMap);
		return modelMap;
	}

	private static void logResult(Logger logger, Result result) {
		if (result.isSuccess()) {
			logger.info("[RESULT]" + ValidatorUtil.KEY_STATUS + ":"
					+ ValidatorUtil.STATUS_SUCCESS );
		} else {
			logger.error("[RESULT]" + ValidatorUtil.KEY_STATUS + ":"
					+ ValidatorUtil.STATUS_FAIL + ValidatorUtil.KEY_ERROR_MSG
					+ ":" + result.getErrMsg());
		}

	}

	private static void processResult(ModelMap modelMap, Result result,ResultCode resultCode) {
		if (result.isSuccess()) {
			//modelMap.put(ValidatorUtil.KEY_STATUS, ValidatorUtil.STATUS_SUCCESS);
			if (0 < result.getModels().size()) {
				if (1 == result.getModels().size()) {
					//modelMap.put(ValidatorUtil.KEY_RESULT,
					//result.getDefaultModel());
					resultCode.setData(result.getDefaultModel());
					
				} else {
					resultCode.setData(result.getModels());
					//modelMap.put(ValidatorUtil.KEY_RESULT, result.getModels());
				}
			}
		} else {
			resultCode.setParams((Integer)ResultCode.UNKNOW_ERROR_CODE[0], (String)ResultCode.UNKNOW_ERROR_CODE[1], result.getErrMsg());
		}
	}
	
	private static void transfer(ResultCode resultCode,ModelMap modelMap){
		modelMap.put("code", resultCode.getCode());
		if(resultCode.getData()!=null){
			modelMap.put("data", resultCode.getData());
		}
		if(!StringUtil.isEmpty(resultCode.getMsg())){
			modelMap.put("msg", resultCode.getMsg());
		}
		if(!StringUtil.isEmpty(resultCode.getDevMsg())){
			modelMap.put("devMsg", resultCode.getDevMsg());
		}
	}

	private static void logParams(Logger logger, Object o) {
		StringBuffer sb = new StringBuffer();
		Class c = o.getClass();
		Field[] fields = c.getDeclaredFields();
		sb.append("PARAMS[");
		for (Field field : fields) {
			try {

				sb.append(field.getName());
				sb.append(":");
				sb.append(invokeMethod(o, field.getName(), null));
				sb.append(" , ");

			} catch (IllegalArgumentException e) {
				logger.error(e);
			} catch (IllegalAccessException e) {
				logger.error(e);
			} catch (Exception e) {
				logger.error(e);
			}
		}
		sb.append("]");
		logger.info(sb.toString());
	}

	public static Object invokeMethod(Object o, String methodName, Object[] args)
			throws Exception {
		Class classes = o.getClass();
		methodName = methodName.substring(0, 1).toUpperCase()
				+ methodName.substring(1);
		Method method = null;
		try {
			method = classes.getMethod("get" + methodName);
		} catch (SecurityException e) {
		} catch (NoSuchMethodException e) {
			return " can't find 'get" + methodName + "' method";
		}

		return method.invoke(o);
	}

	public interface Biz {
		Result process();
	}
}
